<?php

namespace App\Services;

use App\Exceptions\AppException;
use App\Jobs\GenerateAggregate;
use App\Jobs\SendSms;
use App\Libs\Sms\Sms;
use App\Models\District;
use App\Models\SubTask;
use App\Models\SubTaskLog;
use App\Models\Task;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;

class TaskService
{
    public static function create($taskTemplate, $force = false)
    {
        switch ($taskTemplate->frequency) {
            case 'monthly':
                // every month 27th
                $name = $taskTemplate->sheetTemplate->name . '-' . date('Y年m月');
                $key = date('n');
                break;
            case 'once':
                $name = $taskTemplate->name;
                $key = $taskTemplate->name;
                break;
        }

        $task = Task::firstOrNew([
            'sheet_template_id' => $taskTemplate->sheet_template_id,
            'task_template_id' => $taskTemplate->id,
            'frequency' => $taskTemplate->frequency,
            'year' => date('Y'),
            'key' => $key,
        ]);

        if ($task->id) {
            throw new AppException('当前周期任务已存在');
        }

        $task->name = $name;
        $task->notify_type = Task::NOTIFY_TYPE_SMS;
        $task->status = Task::STATUS_INITIALIZED;
        $task->save();
    }

    public static function publish($task, $startDate, $endDate, array $districtIds = [])
    {
        if (empty($districtIds)) {
            throw new AppException('必须选择填报单位');
        }
        if (!in_array($task->status, [Task::STATUS_INITIALIZED, Task::STATUS_CANCELLED])) {
            throw new AppException('任务状态异常');
        }

        try {
            DB::beginTransaction();

            foreach ($districtIds as $districtId) {
                $district = District::find($districtId);
                if (empty($district->reporter)) {
                    throw new AppException($district->name . ' 没有填报人员');
                }
                $st = SubTask::firstOrNew(['task_id' => $task->id, 'district_id' => $districtId]);
                if ($st->id) {
                    throw new AppException($district->name . ' 已存在该任务');
                }
                $st->status = SubTask::STATUS_INITIALIZED;
                $st->save();

                $stl = new SubTaskLog();
                $stl->sub_task_id = $st->id;
                $stl->operator_id = Auth::user()->id ?? 1;
                $stl->operation_type = SubTaskLog::OPERATION_PUBLISH;
                $stl->save();

                if (today() >= Date::parse($startDate) && today() <= Date::parse($endDate)) {
                    $phones = TaskService::nextOperatorPhones($st);
                    SendSms::dispatch($phones, Sms::TMPL1, [TaskService::getSmsTmplTitle($st)]);
                }
            }
            $task->start_date = $startDate;
            $task->end_date = $endDate;
            $task->status = Task::STATUS_PROGRESSING;
            $task->save();

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }

    public static function logSubTask($user, $subTask, $operationType, $comment = null)
    {
        $now = now();
        $latestLog = $subTask->logs()->latest()->first();
        if ($latestLog) {
            $duration = $now->diffInSeconds($latestLog->created_at);
        } else {
            $duration = 0;
        }

        $stl = new SubTaskLog();
        $stl->sub_task_id = $subTask->id;
        $stl->operator_id = $user->id ?? 1;
        $stl->operation_type = $operationType;
        $stl->comment = $comment;
        $stl->duration = $duration;
        $stl->created_at = $now;
        return $stl->save();
    }

    public static function finishSubTask(SubTask $subTask)
    {
        $subTask->status = SubTask::STATUS_COMPLETED;
        $subTask->save();

        self::finishTask($subTask->task);
    }

    public static function isTaskCompleted(Task $task)
    {
        return !$task->subTasks()->where('status', '!=', SubTask::STATUS_COMPLETED)->exists();
    }

    public static function finishTask(Task $task)
    {
        if (!self::isTaskCompleted($task)) {
            return false;
        }

        $task->status = Task::STATUS_COMPLETED;
        $task->save();
        $task->sheetTemplate->aggregateTemplates()->wherePivot('frequency', $task->frequency)->get()->each(function ($template) use ($task) {
            GenerateAggregate::dispatch($template, $task);
        });

        return true;
    }

    public static function nextOperators(SubTask $subTask, $operationType = null)
    {
        if (empty($operationType)) {
            $logs = $subTask->logs()->latest()->first();
            if (!empty($logs)) {
                $operationType = $logs->operation_type;
            }
        }
        switch ($operationType) {
            case SubTaskLog::OPERATION_PUBLISH:
            case SubTaskLog::OPERATION_REJECT1:
                return $subTask->district->reporter;
            case SubTaskLog::OPERATION_REPORT:
            case SubTaskLog::OPERATION_REJECT2:
                return $subTask->district->reviewer;
            case SubTaskLog::OPERATION_REVIEW1:
                return District::getCity()->reviewer;
            case SubTaskLog::OPERATION_REVIEW2:
                return [];
        }
    }

    public static function nextOperatorPhones(SubTask $subTask, $operationType = null)
    {
        $nextOperators = self::nextOperators($subTask, $operationType);
        if (empty($nextOperators)) {
            return [];
        }
        $phones = $nextOperators->pluck('phone')->toArray();
        return $phones;
    }

    public static function getSmsTmplTitle(SubTask $subTask)
    {
        return "{$subTask->task->year}年{$subTask->task->key}月{$subTask->task->sheetTemplate->name}";
    }
}
